//! 串行总线数据解析

#include "bsp.h"

/// @brief 对于电机的RS485数据发送
/// @param argument 
void MotorDataTransmissionTask(void *argument)
{
    /* USER CODE BEGIN StartTask02 */
    /* Infinite loop */
    unsigned char arr[5] = {1,2,3,4,5};
    uint8_t ucKeyCode;		/* 按键代码 */
    static CAN_TxHeaderTypeDef CanTxHeadType = { 0x602 , 0x00 , CAN_ID_STD , CAN_RTR_DATA , 8 , DISABLE , };
    INVERTERCOMMAND SetCommand= {0x0 , 0x0 , 0x0 , 0x0 , 0x0};	//?变频器发送指令
    while(1)
    {
        if(xQueueReceive(MotorRs485Queuesend, &SetCommand, portMAX_DELAY) == pdPASS)
        {//针对于控制指令
			osDelay(20);
			RS485SendMode();
			//BSP_UART_Transmit_IT(&huart1 , (unsigned char *)&SetCommand , sizeof(INVERTERCOMMAND) + 1);
			BSP_UART_Transmit_IT(&huart1 , (unsigned char *)&SetCommand , 8);
			osDelay(5);
			ReceivingMode();
        }		
        osDelay(250);
    }
}

/// @brief 电机的RS485数据解析 + CAN 数据解析 , 使用队列集群进行同步功能 ,  目前只考虑解析了转速信号
/// @param argument 
void MotorDataAnalysisTask(void *argument)
{
	BspUart_t GetBspUart1;
	INVERTERCOMMAND InverterCommand = {0x00 , 0x00, 0x00, 0x00, 0x00};
	int nFrequencySetting = 0x00;		//?	频率设定
	CanRecvMsg_t recvMsg;
	unsigned char SyncPacket[8] = {0x00};
	
	LCDShowQueue member0;
	LCDShowQueue member1;
	LCDShowQueue member2;
	LCDShowQueue member3;

	EventBits_t CaptainExistBits; 	//? 队长存在
	EventBits_t SyncBits; 					//? 同步标志
	unsigned short RunFrequency = 0;							//?	通过CAN获取当前变频器的运行频率
	INVERTERCOMMAND SetCommand= {0x0 , 0x0 , 0x0 , 0x0 , 0x0};	//? 给变频器发送的指令
	INVERTERCOMMANDRETURN returnCommand;						//?	变频器通过RS485返回的指令
	while(1)
	{
		QueueHandle_t activeQueue = (QueueHandle_t)xQueueSelectFromSet(queueSet, portMAX_DELAY);
		if(activeQueue == takeOverRs485Queue)
		{
			if (xQueueReceive(takeOverRs485Queue, &GetBspUart1, 0) == pdPASS) 
			{	//mark 这个变频器返回的数据中不包含当前数据ID , 所以你如果查了2种不同的数据,便且这俩中数据返回的长度切好一样,那么你就没法区分谁是谁
				if(GetBspUart1.rxFlag == 1)
				{	
					returnCommand.InverterAddress = g_tBspUart1.pRxBuf[0];
					returnCommand.Command = g_tBspUart1.pRxBuf[1];
					if(returnCommand.Command == 0x86){
						//tag 变频器返回报错信息
						SEGGER_RTT_CustomFunction(0 , 0, "Frequency Converter is ERROR \r\n");
					}else if(returnCommand.Command == 0x06){
						//tag 变频器返回设置指令
					}else if(returnCommand.Command == 0x03){
						//tag 变频器返回当前频率
						returnCommand.ParameterLength = g_tBspUart1.pRxBuf[2];		
						returnCommand.ParameterData = g_tBspUart1.pRxBuf[3] << 8 | g_tBspUart1.pRxBuf[4];
						xSemaphoreTake(xMutex, portMAX_DELAY); 
						g_RunFrequencyUpdateValue = returnCommand.ParameterData;//update 全局变量"运行频率"更新
						xSemaphoreGive(xMutex);	
						//FrequencyReadingShow(returnCommand.ParameterData);//update LCD显示频率	
						displayFrequency(87, returnCommand.ParameterData);						
					}
				}
			}
		}
	}
}

#pragma pack(1) // 确保没有填充字节
// 定义结构体封装数据
typedef struct {
    uint16_t setFrequency;
    short captainDiff;
    uint8_t memberNum;
} MemberData_t;
#pragma pack() // 恢复默认对齐

/// @brief 辅助函数：发送数据到队列
/// @param queue 
/// @param data 
/// @return 
static BaseType_t sendToMemberQueue(QueueHandle_t queue, MemberData_t* data) {
    if (xQueueSend(queue, data, 0) != pdPASS) {
        // 错误处理：记录日志或采取其他措施
        return pdFAIL;
    }
    return pdPASS;
}

/// @brief 队员逻辑处理
/// @param recvMsg CAN 接收消息
/// @param allocation CAN 分配 ID 信息
static void handleMemberLogic(CanRecvMsg_t* recvMsg, CAN_ALLOCATION_ID* allocation) 
{
    EventBits_t syncBits = xEventGroupGetBits(xSyncEventGroup); // 获取同步标志位状态
    if (allocation->DataType == 0 && allocation->Sync == 1)     // 收到同步类型数据
    {
        xSemaphoreTake(xMutex, 1000 / portTICK_PERIOD_MS);      // 获取互斥锁
        g_CaptainSetFrequencyUpdateValue = (recvMsg->msg_buffer[5] << 8) | recvMsg->msg_buffer[6]; // 更新全局变量：队长的设定频率
        xSemaphoreGive(xMutex);                                 // 释放互斥锁
        xEventGroupSetBits(xCaptainExistEventGroup, 0x01);      // 设置“队长存在”标志位

        if (syncBits & 0x01) // 如果处于同步模式，计算时间间隔为后续同步做准备
        {
            g_can_current_tick = xTaskGetTickCountFromISR();    // 获取当前tick
            if (g_can_last_tick != 0) {
                g_can_interval_ms = (g_can_current_tick - g_can_last_tick) * portTICK_PERIOD_MS; // 计算时间间隔
            }
            g_can_last_tick = g_can_current_tick;               // 更新上一次tick
            g_CaptainSyncDIF = 0;                               // 重置同步差异
            g_SyncCaptaiCanEventGroup = 1;                      // 设置同步事件标志

            // 计算 g_Distance（需根据实际逻辑实现）
            // 示例：假设 g_Distance 是基于频率和时间间隔的某种距离计算
            g_Distance = g_CaptainSetFrequencyUpdateValue * g_can_interval_ms / 1000; // 示例计算，单位需调整
        }
    } 
    else if (allocation->DataType == 1 && allocation->Sync == 1) // 收到频率修改数据
    {
        if (syncBits & 0x01) // 确保处于同步模式
        {
            xEventGroupClearBits(xCo_ChannelEventGroup, 0x03); // 清除同频标志（成功/失败）
            uint16_t runFrequency = (recvMsg->msg_buffer[2] << 8) | recvMsg->msg_buffer[1]; // 获取新频率
            if (UivertorRefreshData(runFrequency) == 0) {       // 更新变频器频率
                xEventGroupSetBits(xFrequencyUpdateLCDCaptain, 0x01); // 设置频率更新标志
            } else {
                // 可选：添加错误处理，例如记录日志
                // printf("Error: Failed to update frequency\n");
            }
            xSemaphoreTake(xMutex, 1000 / portTICK_PERIOD_MS);  // 获取互斥锁
            g_SetFrequencyUpdateValue = runFrequency;           // 更新全局变量：设置频率
            g_CaptainSetFrequencyUpdateValue = runFrequency;    // 更新全局变量：队长的频率
            xSemaphoreGive(xMutex);                             // 释放互斥le锁

            // 更新 g_Distance（需根据实际逻辑实现）
            // 示例：假设 g_Distance 需要根据新频率重新计算
            g_Distance = runFrequency * g_can_interval_ms / 1000; // 示例计算，单位需调整
        }
    }
}

/// @brief 队员逻辑处理
/// @param recvMsg 
/// @param allocation 
//static void handleMemberLogic(CanRecvMsg_t* recvMsg, CAN_ALLOCATION_ID* allocation) 
//{
//    EventBits_t syncBits = xEventGroupGetBits(xSyncEventGroup);	// tag "同步标志"获取
//    if (allocation->DataType == 0 && allocation->Sync == 1)		// tag 收到	同步类型数据
//	{
//        xSemaphoreTake(xMutex, 1000 / portTICK_PERIOD_MS);
//        g_CaptainSetFrequencyUpdateValue = (recvMsg->msg_buffer[5] << 8) | recvMsg->msg_buffer[6];//update 全局变量"获取队长的设定频率"更新
//        xSemaphoreGive(xMutex);
//        xEventGroupSetBits(xCaptainExistEventGroup, 0x01);		//tag "队长存在 "标志位为1 
//        if (syncBits & 0x01) //mark 同步模式下.收到了队长的同步ID数据,那么就开始计算队长的间隔及自己的间隔,为之后的同步模式做准备
//		{
//            g_can_current_tick = xTaskGetTickCountFromISR();
//            if (g_can_last_tick != 0) {
//                g_can_interval_ms = (g_can_current_tick - g_can_last_tick) * portTICK_PERIOD_MS;
//            }
//            g_can_last_tick = g_can_current_tick;
//            g_CaptainSyncDIF = 0;
//            g_SyncCaptaiCanEventGroup = 1;
//        }
//    } 
//	else if (allocation->DataType == 1 && allocation->Sync == 1) // tag 收到.频率修改数据
//	{// mark 我和队长都在同步模式下 , 队长自己修改频率数据 ,并告诉了我
//        if (syncBits & 0x01) 
//		{
//            xEventGroupClearBits(xCo_ChannelEventGroup, 0x03); //tag 清除"同频标志"1和2,1代表:同频成功,2代表:同频失败
//            uint16_t runFrequency = (recvMsg->msg_buffer[2] << 8) | recvMsg->msg_buffer[1];
//            if (UivertorRefreshData(runFrequency) == 0) {
//                xEventGroupSetBits(xFrequencyUpdateLCDCaptain, 0x01);
//            }
//            xSemaphoreTake(xMutex, 1000 / portTICK_PERIOD_MS);
//            g_SetFrequencyUpdateValue = runFrequency;			//update 全局变量"设置频率"更新
//            g_CaptainSetFrequencyUpdateValue = runFrequency;	//update 全局变量"获取队长的频率"更新
//            xSemaphoreGive(xMutex);
//        }
//    }
//}

/// @brief 队长同步数据处理
/// @param recvMsg 
/// @param allocation 
/// @param cardId 
static void handleCaptainSyncData(CanRecvMsg_t* recvMsg, CAN_ALLOCATION_ID* allocation, uint8_t cardId) 
{
    MemberData_t memberData = 
	{
        .setFrequency = (recvMsg->msg_buffer[5] << 8) | recvMsg->msg_buffer[6],
        .captainDiff = (recvMsg->msg_buffer[1] << 8) | recvMsg->msg_buffer[0],
        .memberNum = allocation->DeviceNUM
    };

    switch (cardId) 
	{
        case 0x00: // 队长为0，队员为1,2,3
            if (allocation->DeviceNUM >= 0x01 && allocation->DeviceNUM <= 0x03) {
                sendToMemberQueue(MemberMessag, &memberData);
            }
            break;
        case 0x01: // 队长为1，队员为0,2,3
            if (allocation->DeviceNUM == 0x00 || allocation->DeviceNUM == 0x02 || allocation->DeviceNUM == 0x03) {
                sendToMemberQueue(MemberMessag, &memberData);
            }
            break;
        case 0x02: // 队长为2，队员为0,1,3
            if (allocation->DeviceNUM == 0x00 || allocation->DeviceNUM == 0x01 || allocation->DeviceNUM == 0x03) {
                sendToMemberQueue(MemberMessag, &memberData);
            }
            break;
        case 0x03: // 队长为3，队员为0,1,2
            if (allocation->DeviceNUM <= 0x02) {
                sendToMemberQueue(MemberMessag, &memberData);
            }
            break;
    }
}


/// @brief 队长逻辑处理
/// @param recvMsg 
/// @param allocation 
/// @param cardId 
static void handleCaptainLogic(CanRecvMsg_t* recvMsg, CAN_ALLOCATION_ID* allocation, uint8_t cardId) {
    EventBits_t captainBits = xEventGroupGetBits(xCaptainExistEventGroup);	//tag 队长标识获取
    if (cardId != allocation->DeviceNUM && captainBits == 1 && allocation->Sync == 0) 
	{	
		//mark CaptainExistBits == 1 说明之前的队长标志存在 , 说明他上一次触发来的时候还是队长,现在放弃当队长了
		//mark "CardId" 与收到的  GetAT.DeviceNUM 不相等 , 这个主要是证明我不是队长
		//mark 收到了同步类型数据 , 但是他已经不是队长了 , 说明他之前是队长但是他现在进入了离线模式,主动放弃队长标志
		//tag	换队长
        xEventGroupClearBits(xCaptainExistEventGroup, 0x01); // 清除队长标志
    } 
//	else if (cardId != allocation->DeviceNUM && captainBits == 0 && allocation->Sync == 1)
	else if (cardId != allocation->DeviceNUM && captainBits == 1 && allocation->Sync == 1) 		
	{	
		//tag	队长接收到队员的同步数据包
		//mark CaptainExistBits == 1 说明之前的队长存在标志存在
		//mark "CardId" 与收到的  GetAT.DeviceNUM 不相等 , 这个主要是证明我不是队长		
        if (allocation->DataType == 0) 
		{
            handleCaptainSyncData(recvMsg, allocation, cardId);
        } 
		else 
		{
		//mark 这里就是队员改队长的情况
        }
    }
}

/// @brief 主任务
/// @param argument 
void CanInformationParseTask(void* argument) 
{
    CanRecvMsg_t recvMsg;
    while (1) 
	{
        if (xQueueReceive(CanMessageQueue, &recvMsg, 1000 / portTICK_PERIOD_MS) == pdPASS) 
		{	// tag Can总线收到 "同步类型数据" 和 "修改频率数据"
            CAN_ALLOCATION_ID allocation = estimateCaptain(recvMsg.standard_id);
            if (allocation.CaptainFlag == 1) 
			{// tag 数据中存在队长标识
                handleMemberLogic(&recvMsg, &allocation);
            } 
			else 
			{//	tag 数据不存在队长标志
                handleCaptainLogic(&recvMsg, &allocation, CardId);
            }
        } else {
            // 可选：处理队列接收失败的情况
        }
    }
}

/// @brief 判别是什么类型的数据
/// @param nid 
/// @return 
CAN_ALLOCATION_ID estimateCaptain(unsigned short nid)
{
    CAN_ALLOCATION_ID GetAT;
    
    GetAT.DeviceNUM   = nid & 0x03;         // Bit1~Bit0：设备号
    GetAT.CaptainFlag = (nid >> 2) & 0x01;  // Bit2：队长标识，0:非队长，1:队长
    GetAT.DataType    = (nid >> 3) & 0x01;  // Bit3：数据类型，0:同步数据，1:人工调整
    GetAT.Sync        = (nid >> 4) & 0x01;  // Bit4：同步状态，1:未同步，0:同步
    GetAT.Stall       = (nid >> 5) & 0x01;  // Bit5：失速状态，1:失去速度，0:正常
    
    return GetAT;
}


